{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Waveguide Bend Optimization\n",
    "\n",
    "In this tutorial, we'll examine how we can use Meep's adjoint solver to optimize for a particular design criteria. Specifcally, we'll maximize the transmission around a silicon waveguide bend. This tutorial will illustrate the adjoint solver's ability to quickly calculate gradients for objective functions with multiple objective quantities.\n",
    "\n",
    "To begin, we'll import meep, our adjoint module, `autograd` (as before) and we will also import `nlopt`, a nonlinear optimization package."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using MPI version 3.1, 1 processes\n"
     ]
    }
   ],
   "source": [
    "import meep as mp\n",
    "import meep.adjoint as mpa\n",
    "import numpy as np\n",
    "from autograd import numpy as npa\n",
    "import nlopt\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "mp.verbosity(0)\n",
    "Si = mp.Medium(index=3.4)\n",
    "SiO2 = mp.Medium(index=1.44)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll build a 90 degree bend waveguide with a design region that is 1 micron by 1 micron. We'll discretize our region into a 10 x 10 grid (100 total parameters). We'll send in a narrowband gaussian pulse centered at 1550 nm. We'll also use the same objective function and optimizer object as before."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "resolution = 20\n",
    "\n",
    "Sx = 6\n",
    "Sy = 5\n",
    "cell_size = mp.Vector3(Sx, Sy)\n",
    "\n",
    "pml_layers = [mp.PML(1.0)]\n",
    "\n",
    "fcen = 1 / 1.55\n",
    "width = 0.2\n",
    "fwidth = width * fcen\n",
    "source_center = [-1.5, 0, 0]\n",
    "source_size = mp.Vector3(0, 2, 0)\n",
    "kpoint = mp.Vector3(1, 0, 0)\n",
    "src = mp.GaussianSource(frequency=fcen, fwidth=fwidth)\n",
    "source = [\n",
    "    mp.EigenModeSource(\n",
    "        src,\n",
    "        eig_band=1,\n",
    "        direction=mp.NO_DIRECTION,\n",
    "        eig_kpoint=kpoint,\n",
    "        size=source_size,\n",
    "        center=source_center,\n",
    "    )\n",
    "]\n",
    "\n",
    "design_region_resolution = 10\n",
    "Nx = design_region_resolution + 1\n",
    "Ny = design_region_resolution + 1\n",
    "\n",
    "design_variables = mp.MaterialGrid(mp.Vector3(Nx, Ny), SiO2, Si, grid_type=\"U_MEAN\")\n",
    "design_region = mpa.DesignRegion(\n",
    "    design_variables, volume=mp.Volume(center=mp.Vector3(), size=mp.Vector3(1, 1, 0))\n",
    ")\n",
    "\n",
    "\n",
    "geometry = [\n",
    "    mp.Block(\n",
    "        center=mp.Vector3(x=-Sx / 4), material=Si, size=mp.Vector3(Sx / 2, 0.5, 0)\n",
    "    ),  # horizontal waveguide\n",
    "    mp.Block(\n",
    "        center=mp.Vector3(y=Sy / 4), material=Si, size=mp.Vector3(0.5, Sy / 2, 0)\n",
    "    ),  # vertical waveguide\n",
    "    mp.Block(\n",
    "        center=design_region.center, size=design_region.size, material=design_variables\n",
    "    ),  # design region\n",
    "    # mp.Block(center=design_region.center, size=design_region.size, material=design_variables,\n",
    "    #         e1=mp.Vector3(x=-1).rotate(mp.Vector3(z=1), np.pi/2), e2=mp.Vector3(y=1).rotate(mp.Vector3(z=1), np.pi/2))\n",
    "    #\n",
    "    # The commented lines above impose symmetry by overlapping design region with the same design variable. However,\n",
    "    # currently there is an issue of doing that; We give an alternative approach to impose symmetry in later tutorials.\n",
    "    # See https://github.com/NanoComp/meep/issues/1984 and https://github.com/NanoComp/meep/issues/2093\n",
    "]\n",
    "\n",
    "sim = mp.Simulation(\n",
    "    cell_size=cell_size,\n",
    "    boundary_layers=pml_layers,\n",
    "    geometry=geometry,\n",
    "    sources=source,\n",
    "    eps_averaging=False,\n",
    "    resolution=resolution,\n",
    ")\n",
    "\n",
    "TE_top = mpa.EigenmodeCoefficient(\n",
    "    sim, mp.Volume(center=mp.Vector3(0, 1, 0), size=mp.Vector3(x=2)), mode=1\n",
    ")\n",
    "ob_list = [TE_top]\n",
    "\n",
    "\n",
    "def J(alpha):\n",
    "    return npa.abs(alpha) ** 2\n",
    "\n",
    "\n",
    "opt = mpa.OptimizationProblem(\n",
    "    simulation=sim,\n",
    "    objective_functions=J,\n",
    "    objective_arguments=ob_list,\n",
    "    design_regions=[design_region],\n",
    "    fcen=fcen,\n",
    "    df=0,\n",
    "    nf=1,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As before, we'll visualize everything to ensure our monitors, boundary layers, and geometry are drawn correctly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x0 = 0.5 * np.ones((Nx * Ny,))\n",
    "opt.update_design([x0])\n",
    "\n",
    "opt.plot2D(True)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now define a cost function wrapper that we can feed into our `nlopt` optimizer. `nlopt` expects a python function where the gradient is passed in place. In addition, we'll update a list with every objective function call so we can track the cost function evolution each iteration.\n",
    "\n",
    "Notice the `opt` adjoint solver object requires we pass our numpy array of design parameters within an additional list. This is because the adjoint solver can solve for multiple design regions simultaneously. It's useful to break up each region's parameters into indvidual numpy arrays. In this simple example, we only have one design region."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "evaluation_history = []\n",
    "sensitivity = [0]\n",
    "\n",
    "\n",
    "def f(x, grad):\n",
    "    f0, dJ_du = opt([x])\n",
    "    f0 = f0[0]  # f0 is an array of length 1\n",
    "    if grad.size > 0:\n",
    "        grad[:] = np.squeeze(dJ_du)\n",
    "    evaluation_history.append(np.real(f0))\n",
    "    sensitivity[0] = dJ_du\n",
    "    return np.real(f0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can set up the actual optimizer engine. We'll select the Method of Moving Asymptotes because it's a gradient based method that allows us to specify linear and nonlinear constraints. For now, we'll simply bound our parameters between 0 and 1.\n",
    "\n",
    "We'll tell our solver to maximize (rather than minimize) our cost function, since we are trying to maximize the power transmission around the bend.\n",
    "\n",
    "We'll also tell the optimizer to stop after 10 function calls. This will keep the wait time short and demonstrate how powerful the adjoint solver is."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "algorithm = nlopt.LD_MMA\n",
    "n = Nx * Ny\n",
    "maxeval = 10\n",
    "\n",
    "solver = nlopt.opt(algorithm, n)\n",
    "solver.set_lower_bounds(0)\n",
    "solver.set_upper_bounds(1)\n",
    "solver.set_max_objective(f)\n",
    "solver.set_maxeval(maxeval)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n"
     ]
    }
   ],
   "source": [
    "x = solver.optimize(x0);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that the solver is done running, we can evaluate our progress."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure()\n",
    "plt.plot(evaluation_history, \"o-\")\n",
    "plt.grid(True)\n",
    "plt.xlabel(\"Iteration\")\n",
    "plt.ylabel(\"FOM\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can update our optimization object and visualize the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "opt.update_design([x])\n",
    "opt.plot2D(\n",
    "    True,\n",
    "    plot_monitors_flag=False,\n",
    "    output_plane=mp.Volume(center=(0, 0, 0), size=(2, 2, 0)),\n",
    ")\n",
    "plt.axis(\"off\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We quickly see that the solver improves the design, but because of the way we chose to formulate our cost function, it's difficult to quantify our results. After all, how good is a figure of merit (FOM) of 70?\n",
    "\n",
    "To overcome this, we'll slightly modify our objective function to include an extra monitor just after the source. This monitor will track however much power is transmitted into the waveguide. We can then normalize the upper monitor's response by this parameter:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "TE0 = mpa.EigenmodeCoefficient(\n",
    "    sim, mp.Volume(center=mp.Vector3(-1, 0, 0), size=mp.Vector3(y=2)), mode=1\n",
    ")\n",
    "ob_list = [TE0, TE_top]\n",
    "\n",
    "\n",
    "def J(source, top):\n",
    "    return npa.abs(top / source) ** 2\n",
    "\n",
    "\n",
    "opt.objective_functions = [J]\n",
    "opt.objective_arguments = ob_list\n",
    "opt.update_design([x0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll refresh our solver and try optimizing again:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n",
      "Starting forward run...\n",
      "Starting adjoint run...\n",
      "Calculating gradient...\n"
     ]
    }
   ],
   "source": [
    "evaluation_history = []\n",
    "solver = nlopt.opt(algorithm, n)\n",
    "solver.set_lower_bounds(0)\n",
    "solver.set_upper_bounds(1)\n",
    "solver.set_max_objective(f)\n",
    "solver.set_maxeval(maxeval)\n",
    "x = solver.optimize(x0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can view our results and normalize the FOM as the percent power transmission."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure()\n",
    "plt.plot(np.array(evaluation_history) * 100, \"o-\")\n",
    "plt.grid(True)\n",
    "plt.xlabel(\"Iteration\")\n",
    "plt.ylabel(\"Transmission (%)\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We once again clearly see great improvement, from about 5% transmission to about 85%, after just 10 iterations!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Achieved an improvement of 28.0x\n"
     ]
    }
   ],
   "source": [
    "improvement = max(evaluation_history) / min(evaluation_history)\n",
    "print(\"Achieved an improvement of {0:1.1f}x\".format(improvement))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, we can visualize our new geometry. We see that the design region naturally connected the two waveguide segements in a bend fashion and has placed several other distinctive features around the curve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "opt.update_design([x])\n",
    "opt.plot2D(\n",
    "    True,\n",
    "    plot_monitors_flag=False,\n",
    "    output_plane=mp.Volume(center=(0, 0, 0), size=(2, 2, 0)),\n",
    ")\n",
    "plt.axis(\"off\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also visualize the sensitivity to see which geometric areas are most sensitive to perturbations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(np.rot90(np.squeeze(np.abs(sensitivity[0].reshape(Nx, Ny)))));"
   ]
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
